home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
msgq160s.arc
/
BUFMSG.C
< prev
next >
Wrap
Text File
|
1991-10-26
|
9KB
|
416 lines
/*
* BUFMSG.C - Message Buffering
*
* Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
*
*/
/*#define TIMING*/ /* for optimization info */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef TIMING
#include <time.h>
#include <stdio.h>
#endif
#include "msged.h"
#ifdef TIMING
static void watch(int chk)
{
static clock_t start;
if (chk != 0) {
clock_t dif = clock()-start;
fprintf(stderr,"%-3d %ld\n", chk, dif);
} /* else */
if (chk == -1)
do {} while (getchar() != '\n');
start = clock();
} /* watch */
#else
# define watch(dummy)
#endif
void clearbuffer(BUFFER *buf)
{
LINE *curline;
if ((curline = buf->first) != NULL) {
while (curline->next != NULL) {
curline = curline->next;
ptrfree(curline->prev->text);
curline->prev->next = NULL;
ptrfree(curline->prev);
curline->prev = NULL;
}
if (curline->text)
ptrfree(curline->text);
curline->text = NULL;
ptrfree(curline);
curline = NULL;
buf->first = NULL;
buf->last = NULL;
}
}
#if ZAPTHISOUT /* OLD NEW VERSION */
static void normalize(char *s);
BUFFER buffer(char **ss)
{
char *tmp, *t, *t1, *s;
LINE *p;
BUFFER buf;
int i;
int column;
/* init the buffer variables */
buf.first = buf.last = NULL;
clearbuffer(); /* clear global buffer (bad code) */
watch(0);
normalize(*ss); /* remove soft \r, convert \r\n to \n */
watch(2);
if ((*ss = (char *) realloc(*ss, strlen(*ss) + 1)) == NULL)
return buf;
s = *ss;
/* wrap the text into the buffer */
if ((t = (char *) calloc(1, (rm + rm/2))) == NULL)
return buf;
if ((tmp = (char *) calloc(1, (rm + rm/2))) == NULL) {
ptrfree(t);
return buf;
}
i = 0;
buf.first = NULL;
column = 0;
while (*s != EOS) {
column++;
if (*s == '\t') {
s++;
*(t + i) = ' ';
while (column % tabsize) {
i++;
*(t + i) = ' ';
column++;
}
}
else
*(t + i) = *s++;
/* if ((strlen(t) > rm) || (*(t + i) == '\n')) */
/* if (strlen(t) > rm) */
if ((i >= rm) || (*(t + i) == '\n')) {
if ((workcount++ & 31) == 0)
working(TRUE);
column = 0;
if (i >= rm) {
memset(tmp, 0, (rm + rm/2));
t1 = t + i;
while (!isspace(*t1) && (t1 > t))
t1--;
if (t1 <= t) {
t1 = t + i;
while (!ispunct(*t1) && (t1 > t))
t1--;
}
if (t1 <= t)
t1 = t + i - 1;
while (isspace(*t1))
t1++;
strcpy(tmp, t1);
*t1 = '\0';
}
else
memset(tmp, 0, (rm + rm/2));
if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
ptrfree(t);
ptrfree(tmp);
return buf;
}
if ((p->text = strdup(t)) == NULL) {
ptrfree(p);
ptrfree(t);
ptrfree(tmp);
return buf;
}
if (*p->text == '\01')
p->hide = 1;
{ register char *otmp = strchr(p->text,'>');
if ((otmp != NULL) && (otmp - p->text < GUTTER))
p->quote = 1;
} /* island */
if (buf.first == NULL) {
buf.first = p;
buf.last = p;
p->next = NULL;
p->prev = NULL;
memset(t, 0, (rm + rm/2));
strcpy(t, tmp);
i = strlen(t);
continue;
}
p->next = buf.last->next;
buf.last->next = p;
p->prev = buf.last;
buf.last = p;
memset(t, 0, (rm + rm/2));
strcpy(t, tmp);
i = strlen(t);
}
else
i++;
} /* while */
watch(3);
if (strlen(t) > 0) {
if ((p = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
ptrfree(tmp);
ptrfree(t);
return buf;
}
if ((p->text = strdup(t)) == NULL) {
ptrfree(p);
ptrfree(t);
ptrfree(tmp);
return buf;
}
if (buf.first == NULL) {
buf.first = p;
buf.last = p;
p->next = NULL;
p->prev = NULL;
}
else {
p->next = buf.last ->next;
buf.last->next = p;
p->prev = buf.last;
buf.last = p;
}
if (*p->text == '\01')
p->hide = 1;
if (((strchr(p->text,'>') - p->text) < GUTTER) && (strchr(p->text,'>')))
p->quote = 1;
}
watch(-1);
ptrfree(tmp);
ptrfree(t);
if (buf.first != NULL)
buf.first->prev = NULL;
if (buf.last != NULL)
buf.last->next = NULL;
working(FALSE);
return buf;
} /* buffer */
static void normalize(char *s)
{
char *tmp = s;
char *org = s;
while (*s != EOS) {
switch (*s) {
case (char) 0x8d:
case (char) 0x0a:
s++;
continue;
case (char) 0x0d:
s++;
*tmp = '\n';
break;
default:
*tmp = *s++;
break;
}
tmp++;
}
*tmp = EOS;
if (rot13 != 0)
for (s = org; *s != EOS; s++)
*s = dorot13(*s);
}
#endif
/*
* Copy lookahead characters to line buffer
* s is start, scol is col at start
* p is end (inclusive)
* *d is destination and is updated and zero-terminated
* returns pointer p+1
*/
static char *copychars(int *scol, char *s, char *p, char **d)
{
int c;
while (s <= p) {
switch (*s) {
case '\n':
case (char)0x8d:
++s;
break;
case '\t':
c = tabsize-(*scol % tabsize); /* spaces to skip */
*scol += c;
while (c--)
*(*d)++ = ' ';
++s;
break;
case '\r':
*(*d)++ = '\n'; ++s;
++(*scol);
break;
default:
*(*d)++ = *s++;
++(*scol);
break;
} /* switch */
}
*(*d) = EOS;
return s;
} /* copychars */
static BOOLEAN addline(BUFFER *buf, char *text)
{
static int workcount = 0; /* slow down working indicator */
LINE *p;
char *grin;
if ((workcount++ & 31) == 0)
working(TRUE);
if ((p = insertline(buf, NULL, text)) == NULL)
return FALSE;
if (text[0] == '\01')
p->hide = 1;
text = strchr(p->text, '>');
grin = strchr(p->text, '<'); /* don't quote "<grin>" at start */
if ((text != NULL) && (text - p->text < GUTTER) &&
((grin == NULL) || (grin > text)))
p->quote = 1;
return TRUE;
} /* addline */
BUFFER buffer(char **ss) /* NEW(est) version */
{
register char *s, *p;
int scol, pcol;
char *d, *text;
BUFFER buf;
buf.first = buf.last = NULL;
clearbuffer(&msgbuf); /* clear global (yuck) buffer */
text = (char *)malloc(rm + rm/2); /* add some fudge for taste */
if (text == NULL) return buf; /* sorry pal */
if (rot13 != 0) /* do rotation pass */
for (s = *ss; *s != EOS; s++)
*s = dorot13(*s);
p = s = *ss; pcol = scol = 0; /* s is source, p is peek */
d = text; *d = EOS; /* d is dest */
for (;;) { /* loop over p by 1 (sometimes backtrack to checkpoint) */
/* pcol is col at p (increases or stays same) */
/* s is last checkpoint */
/* scol is col at s */
/* d is destination inside text */
/* if at end of buffer, finish current line and exit */
if (*p == EOS) { /* end of text */
if (p > s) { /* we still have sometime left */
(void)copychars(&scol, s, p-1, &d);
(void)addline(&buf, text);
} /* if */
break; /* end of buffer */
/* if at/past margin, start new line or smash current line (break badly) */
} else if (pcol >= rm) { /* at margin */
if (scol == 0) { /* bad break! */
p = s = copychars(&scol, s, p, &d);
pcol = scol = 0;
if (!addline(&buf, text))
break;
} else { /* freeze line at last checkpoint */
if (!addline(&buf, text))
break;
p = s; pcol = scol = 0; /* start over at last checkpoint */
} /* else */
d = text; *d = EOS;
} else if (*p == '\r') { /* end of line */
p = s = copychars(&scol, s, p, &d);
pcol = scol = 0;
if (!addline(&buf, text))
break;
d = text; *d = EOS;
/* can break line here */
} else if ((*p == ' ') || (*p == '\t') || (*p == '-')) {
p = s = copychars(&scol, s, p, &d); /* 'checkpoint' */
pcol = scol;
} else if ((*p == '\n') || (*p == (char)0x8d)) { /* ignore */
++p;
} else { /* all other characters */
++pcol;
++p;
} /* else */
} /* endless */
ptrfree(text);
working(FALSE); /* remove indicator */
return buf;
} /* buffer */